#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    :   EditEvents
@Time    :   2023/02/26 12:01:47
@author  :   Eval
@Version :   1.0
@Describe:   事件编辑器
'''
from PySide6.QtCore import (QRect, QSize,Qt)
from PySide6.QtWidgets import (QComboBox, QFrame, QLabel, QScrollArea, QWidget,QVBoxLayout,QLineEdit,QPlainTextEdit,QCheckBox)
from json import loads as JsonLoads
from conf.Edit.MyLael import *
from conf.Edit.MyCanvasWidget import *
from conf.GameLogin import *
from copy import deepcopy

class EditEventsForm(object):
    def setupUi(self, Form):
        self.frame = QFrame(Form)
        self.frame.setGeometry(QRect(0, 0, 600, 600))
        self.frame.setStyleSheet(u"background-color: rgb(255, 255, 255);")
        self.frame.setFrameShape(QFrame.StyledPanel)
        self.frame.setFrameShadow(QFrame.Raised)

class ChildUI(QWidget):
    def __init__(self,form):
        super(ChildUI,self).__init__()
        self.form:MyWidget = form
        self.ui = EditEventsForm()
        self.ui.setupUi(self)
        self.setWindowTitle("事件编辑器")
        self.setWindowIcon(QPixmap("lib/images/editIco.png"))
        self.resize(600, 550)
        self.setMinimumSize(QSize(600, 600))
        self.setMaximumSize(QSize(600, 600))

        # 存放当前所有的事件ui组件
        self.ControlsList:list[MyCanvasWidget] = []

        # 被选中的子组件
        self.cureChild = None

        self.posEvent:list = []
        self.EditEvents = {}  #从配置文件 EditEvents.json 中获取数据

        self.__initControls()

    def closeEvent(self,e) -> None:
        print_info("关闭ui编辑器")

    def showWin(self,x=0,y=0,pos:list=None):
        """拦截原本自带的show方法,执行一些初始化的操作"""
        if not pos is None:
            x,y = int(pos[0]),int(pos[1])
        # 如果这个点有事件,那么执行解析
        self.posEvent = deepcopy(self.form.mapEvn.get(f"{x},{y}"))
        self.posint.setText(f"{x},{y}")
        self.analysisEvent()
        # 置顶
        self.setWindowFlags(Qt.WindowType.WindowShadeButtonHint)
        # 取消置顶,  将窗体置顶又立刻取消置顶, ps:窗体已经创建出来, 并没有关闭, 
        # 但是点击主窗体之后又被挡住了, 再次点击事件编辑显示 编辑事件ui的时候,不置顶就会导致窗体不能显示在最上层,还是被挡住的状态, 但又不需要一直置顶,所以置顶之后又执行取消置顶
        self.setWindowFlags(Qt.WindowType.Widget)
        # 渲染ui
        self.show()

    def __initControls(self):
        """创建时初始化组件"""
        # 保存按钮
        self.BtnSave = self.form.ui.createBtnBox("保存",100,10,50,24,form=self,event=self.saveEvent)
        # 追加事件按钮
        self.BtnEvent = self.form.ui.createBtnBox("添加事件",487, 5, 50, 24,form=self,event=self.addEvent)
        
        # 坐标label
        self.posint = self.form.ui.createLineBox(10,15,45,20,form=self,labName="坐标:")
        self.posint.setEnabled(False)

        
        self.form.ui.createLab("是否选中:",10,50,40,20,form=self)
        self.currCheck = self.form.ui.createCheckBox(70,55,isChecked=False,form=self)
        self.currCheck.setEnabled(False)  # 不能手动修改,
        # 根据游标 修改事件块的位置
        self.BtnSaveCurSor = self.form.ui.createBtnBox("更新位置",240,50,50,24,form=self,event=lambda:self.setCursor())

        # 加载事件模板数据
        with open(f"conf\Edit\EditEvents.json","r",encoding="utf-8") as file:
            self.EditEvents = JsonLoads(file.read())
            self.eventCombox:QComboBox = self.form.ui.createComboBox(340, 10, 141, 22,list(self.EditEvents.keys()),self)

        self.scrollArea:QScrollArea = QScrollArea(self)
        self.scrollArea.setGeometry(QRect(5, 100, 591, 490))
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setFocusPolicy(Qt.FocusPolicy.NoFocus)
        # 滚动区域的容器
        self.scrollContent = QWidget(self)
        self.scrollContent.setGeometry(QRect(0, 0, 589, 480))
        
        # 滚动区域 的布局
        self.scrollLayout = QVBoxLayout(self)
        self.scrollContent.setLayout(self.scrollLayout)
        self.scrollArea.setWidget(self.scrollContent)

        # 当前事件的游标位置, 添加事件时,根据游标的位置插入
        self.EventCursor = 0
        # 游标label
        self.EventCursorLab = self.form.ui.createLab("游标",form=self.scrollArea,style="background-color:rgb(230,50,50);color:rgb(255,255,255);",MW=40)
        #  游标输入框
        self.cursorLab = self.form.ui.createLineBox(100,50,form=self,labName="游标:")
        # 修改游标位置
        self.BtnSaveCurSor = self.form.ui.createBtnBox("保存游标",240,50,50,24,form=self,event=lambda:self.setCursor())


    def analysisEvent(self,scroll=True):
        self.currCheck.setChecked(False)
        # 刷新原本的内容
        if len(self.ControlsList):
            for con in self.ControlsList:
                con.destroy()
                con.hide()
            self.ControlsList.clear()
        # 如果这个点没有事件,那么清空之前残留的ui之后,跳出
        if not self.posEvent:
            self.scrollContent.setFixedHeight(0)
            return
        offstY = 50
        for index,e in enumerate(self.posEvent):
            control:QLabel =None
            self.EventCursor += 1
            match(e["type"]):
                case "speakTip":
                    # 对话事件
                    control = self.form.ui.Canvas_speakTip(self,e)
                    
                case "setBlock":  # 转换图块
                    control = self.form.ui.Canvas_SetBlock(self,e)

                case "openDoor":  # 开门
                    control = self.form.ui.Canvas_openDoor(self,e)
                    
                case "closeDoor":  # 关门
                    control = self.form.ui.Canvas_closeDoor(self,e)

                case "playSound":  # 播放音效
                    control = self.form.ui.Canvas_playSound(self,e)

                case "hide":  # 隐藏事件
                    control = self.form.ui.Canvas_hide(self,e)

                case "tip":  # 消息提示
                    control = self.form.ui.Canvas_tip(self,e)

                case "input":  # 接受输入
                    control = self.form.ui.Canvas_input(self,e)

                case "useItem":  # 使用道具
                    control = self.form.ui.Canvas_useItem(self,e)
                    
                case "addItem":  # 获得道具
                    control = self.form.ui.Canvas_addItem(self,e)

                case "exit":  # 立刻结束当前事件
                    control = self.form.ui.Canvas_exit(self)
                # case "if":  # if else 事件 比较复杂,以后在啃
                #     control = self.form.ui.Canvas_if(self,e)
                case "changeFloor":  # 楼层切换
                    control = self.form.ui.Canvas_changeFloor(self,e)

                case "comment":  # 注释
                    control = self.form.ui.Canvas_comment(self,e)

                case _: # 缺省值
                    control = self.form.ui.Canvas_None(self,conName=e["type"])
                    
            if not control is None:
                control.setObjectName(f"{index}")
                self.ControlsList.append(control)
                self.scrollLayout.addWidget(control)
                offstY += control.height() + 5

            # 设置游标
            self.setCursor(index+1)
            # self.EventCursor = index

        self.scrollContent.setFixedHeight(offstY + self.EventCursorLab.height())
        # 将滚动条移动至底部
        if scroll:
            self.scrollArea.verticalScrollBar().setValue(offstY)
        
    # 添加事件
    def addEvent(self):
        if self.posEvent is None:
            self.posEvent = []
        # 增加的事件使用深度拷贝进行追加, 防止数据污染
        newEv = deepcopy(self.EditEvents[self.eventCombox.currentText()])
        if not newEv.get("loc") is None:
            pos = self.posint.text().split(",")
            newEv["loc"] = [int(pos[0]),int(pos[1])]
        self.posEvent.insert(self.EventCursor,newEv)
        self.analysisEvent()
        # 将当前事件点的事件进行缓存,不然执行这个方法之后,之前的数据就会被重置
        self.saveEventCache()
 
    def mousePressEvent(self, event: QMouseEvent) -> None:
        if event.button() == Qt.MouseButton.RightButton:
            if self.cureChild is None:
                return
            self.currCheck.setChecked(False)
            focus:list[QLineEdit] = self.cureChild.children()
            for chi in focus:
                if type(chi) == QLineEdit or type(chi) == QPlainTextEdit:
                    chi.clearFocus()
        return super().mouseReleaseEvent(event)

    def keyPressEvent(self,e:QKeyEvent):
        """键盘事件"""
        if not self.cureChild is None:
            index = int(self.cureChild.objectName())
            if e.key() == Qt.Key.Key_Delete:
                self.posEvent.pop(index)
                self.ControlsList.pop(index)
                self.cureChild.destroy()
                self.cureChild.hide()
                self.cureChild = None
                self.currCheck.setChecked(False)
                # 将当前事件点的事件进行缓存,不然执行这个方法之后,之前的数据就会被重置
                self.saveEventCache()

                self.analysisEvent(False)

            elif e.key() == Qt.Key.Key_PageUp:
                if index >= 1:
                    self.posEvent[index],self.posEvent[index-1] = self.posEvent[index-1],self.posEvent[index]
                    self.ControlsList[index],self.ControlsList[index-1] = self.ControlsList[index-1],self.ControlsList[index]
                    self.cureChild.setObjectName(str(int(index)-1))
                    # 将当前事件点的事件进行缓存,不然执行这个方法之后,之前的数据就会被重置
                    self.saveEventCache()
                    self.analysisEvent(False)
                    
            elif e.key() == Qt.Key.Key_PageDown:
                if index < len(self.posEvent)-1:
                    self.posEvent[index],self.posEvent[index+1] = self.posEvent[index+1],self.posEvent[index]
                    self.ControlsList[index],self.ControlsList[index+1] = self.ControlsList[index+1],self.ControlsList[index]
                    self.cureChild.setObjectName(str(int(index)+1))
                    # 将当前事件点的事件进行缓存,不然执行这个方法之后,之前的数据就会被重置
                    self.saveEventCache()
                    self.analysisEvent(False)

            elif e.key() == Qt.Key.Key_Escape:
                focus:list[QLineEdit] = self.cureChild.children()
                self.currCheck.setChecked(False)
                for chi in focus:
                    if type(chi) == QLineEdit or type(chi) == QPlainTextEdit:
                        chi.clearFocus()

    def saveEventCache(self):
        """保存事件事件缓存数据,"""
        for index,con in enumerate(self.ControlsList):
            focus:list[QLineEdit] = con.children()
            for conChil in focus:
                self.updateControls(conChil,index)
                continue
    
    def saveEvent(self):
        """保存事件"""
        self.saveEventCache()
        if not self.posEvent:
            if not self.form.mapEvn.get(self.posint.text()) is None:
                del self.form.mapEvn[self.posint.text()] 
        else:
            self.form.mapEvn[self.posint.text()] = deepcopy(self.posEvent)
            
        self.form.saveMap(force=True)  # 强制保存事件
        self.form.updateMap()

    def setCursor(self,value=None):
        """更新游标位置"""
        if value is None:
            value = self.cursorLab.text()
        if str(value).isdigit():
            if int(value) <0 or int(value) > len(self.ControlsList):
                self.form.addLog("游标的值必须在事件块的长度之间",level=3)
                return
            self.EventCursor = int(value)

            self.cursorLab.setText(f"{self.EventCursor}")
            self.EventCursorLab.setText(f"游标:{self.EventCursor}")
            self.form.addLog("更新游标位置成功")
            self.EventCursorLab.raise_()
        else:
            self.form.addLog("游标的值必须为整数",level=3)

    def updateControls(self,conChil:QLineEdit or QCheckBox,index:int):
        """将组件的值更新到文件对象"""
        keyStr = {
            "楼层":"floorId",
            "图块":"blockName",
            "msg":"text",
            "id":"id",
            "value":"value",
            "img":"icon",
            "music":"name",
            "value":"value",
            "删除事件":"remove",
            "key":"needKey"
        }
        if(type(conChil) == QLineEdit):
            if conChil.objectName() == "x":
                self.posEvent[index]["loc"][0] = conChil.text()
            elif conChil.objectName() == "y":
                self.posEvent[index]["loc"][1] = conChil.text()
            elif conChil.objectName() == "标题":
                self.posEvent[index]["data"][0] = conChil.text()
            elif conChil.objectName() == "图像":
                self.posEvent[index]["data"][1] = conChil.text()
            else:
                item = keyStr.get(conChil.objectName())
                if item:
                    self.posEvent[index][item] = conChil.text()
                else:
                    print_error(f"错误的属性key:{conChil.objectName()}")

        elif(type(conChil) == QCheckBox):
            item = keyStr.get(conChil.objectName())
            if item:
                self.posEvent[index][item] = conChil.isChecked()
            else:
                print_error(f"错误的属性key:{conChil.objectName()}")

        elif(type(conChil) ==QPlainTextEdit):
            if conChil.objectName() == "消息":
                self.posEvent[index]["msg"] = conChil.toPlainText()

